<!--
Copyright (c) 2024 Industrial Shields. All rights reserved

This file is part of node-red-librpiplc.

node-red-librpiplc is free software: you can redistribute
it and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, either version
3 of the License, or (at your option) any later version.

node-red-librpiplc is distributed in the hope that it will
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->

<script type="text/javascript">
	const rpiplcDigitalInputsAnalog0 = [ "I0.0", "I0.1", "I0.2", "I0.3", "I0.4", "I0.5", "I0.6", "I0.7", "I0.8", "I0.9", "I0.10", "I0.11", "I0.12", ];
	const rpiplcDigitalInputsAnalog1 = [ "I1.0", "I1.1", "I1.2", "I1.3", "I1.4", "I1.5", "I1.6", "I1.7", "I1.8", "I1.9", "I1.10", "I1.11", "I1.12", ];
	const rpiplcDigitalInputsAnalog2 = [ "I2.0", "I2.1", "I2.2", "I2.3", "I2.4", "I2.5", "I2.6", "I2.7", "I2.8", "I2.9", "I2.10", "I2.11", "I2.12", ];
	const rpiplcDigitalInputsRelay0 = [ "I0.0", "I0.1", "I0.2", "I0.3", "I0.4", "I0.5", ];
	const rpiplcDigitalInputsRelay1 = [ "I1.0", "I1.1", "I1.2", "I1.3", "I1.4", "I1.5", ];
	const rpiplcDigitalInputsRelay2 = [ "I2.0", "I2.1", "I2.2", "I2.3", "I2.4", "I2.5", ];

	const rpiplcV6ExtraDigitalInputs = ["PIN8", "OPTO_IN_1", "OPTO_IN_2", "INT31"];
	const rpiplcV6DigitalInputPins = {
		"RPIPLC_19R": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0],
		"RPIPLC_21": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0],
		"RPIPLC_38AR": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsRelay1],
		"RPIPLC_38R": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0, ...rpiplcDigitalInputsRelay1],
		"RPIPLC_42": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsAnalog1],
		"RPIPLC_50RRA": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsAnalog2],
		"RPIPLC_53ARR": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsRelay2],
		"RPIPLC_54ARA": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsAnalog2],
		"RPIPLC_57AAR": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsAnalog1, ...rpiplcDigitalInputsRelay2],
		"RPIPLC_57R": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsRelay2],
		"RPIPLC_58": [...rpiplcV6ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsAnalog1, ...rpiplcDigitalInputsAnalog2]
	};

	const rpiplcV4ExtraDigitalInputs = ["PIN8"];
	const rpiplcV4DigitalInputPins = {
		"RPIPLC_19R": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0],
		"RPIPLC_21": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0],
		"RPIPLC_38AR": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsRelay1],
		"RPIPLC_38R": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0, ...rpiplcDigitalInputsRelay1],
		"RPIPLC_42": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsAnalog1],
		"RPIPLC_50RRA": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsAnalog2],
		"RPIPLC_53ARR": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsRelay2],
		"RPIPLC_54ARA": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsAnalog2],
		"RPIPLC_57AAR": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsAnalog1, ...rpiplcDigitalInputsRelay2],
		"RPIPLC_57R": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsRelay2],
		"RPIPLC_58": [...rpiplcV4ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsAnalog1, ...rpiplcDigitalInputsAnalog2]
	};

	const rpiplcV3ExtraDigitalInputs = [];
	const rpiplcV3DigitalInputPins = {
		"RPIPLC_19R": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0],
		"RPIPLC_21": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0],
		"RPIPLC_38AR": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsRelay1],
		"RPIPLC_38R": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0, ...rpiplcDigitalInputsRelay1],
		"RPIPLC_42": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsAnalog1],
		"RPIPLC_50RRA": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsAnalog2],
		"RPIPLC_53ARR": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsRelay2],
		"RPIPLC_54ARA": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsAnalog2],
		"RPIPLC_57AAR": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsAnalog1, ...rpiplcDigitalInputsRelay2],
		"RPIPLC_57R": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsRelay0, ...rpiplcDigitalInputsRelay1, ...rpiplcDigitalInputsRelay2],
		"RPIPLC_58": [...rpiplcV3ExtraDigitalInputs, ...rpiplcDigitalInputsAnalog0, ...rpiplcDigitalInputsAnalog1, ...rpiplcDigitalInputsAnalog2]
	};

	const pinsMapDigitalInputPins = {
		"RPIPLC_V6": rpiplcV6DigitalInputPins,
		"RPIPLC_V4": rpiplcV4DigitalInputPins,
		"RPIPLC_V3": rpiplcV3DigitalInputPins,
		"UPSAFEPI_V6": {"UPSAFEPI": []},
		"GATEBERRY_V9": {"GATEBERRY": []},
		"TOUCHBERRY_PI_V1": {"TOUCHBERRY_PI": ["I0_4_20", "I1_4_20", "I0", "I1", "I2", "I3", "I4", "CS0", "CS1"]},
	};

	RED.nodes.registerType("rpiplc-digital-read", {
		category: "Industrial Shields",
		color: "#C7E9C0",

		defaults: {
			rpiplc: { value: null, type: "rpiplc-config", required: true },
			pin: { value: null, required: true },
			name: { value: "" },
		},

		inputs: 1,
		outputs: 1,

		icon: "serial.svg",
		align: "left",
		labelStyle: "node_label",
		label: function() {
			if (this.name) {
				return this.name;
			}
			if (this.pin) {
				let pinStr = this.pin !== "CUSTOM" ? this.pin : "custom"
				return `read ${pinStr}`;
			}
			return "invalid digital read";
		},
		paletteLabel: function() {
			return this.name || "digital read";
		},

		oneditprepare: function() {
			const digitalReadNode = this;

			$("#node-input-rpiplc").change(function() {
				const hideInputDiv = $("#hide-node-input-pin");
				const pinSelect = $("#node-input-pin");

				function hidePins() {
					hideInputDiv.hide();
					pinSelect.empty();
					pinSelect.append($("<option></option>").val(null).text("You found a bug!"));
				}

				const configId = $(this).val();
				if (!configId) {
					hidePins();
					return;
				}
				const configNode = RED.nodes.node(configId);
				if (!configNode) {
					hidePins();
					return;
				}

				const version = configNode.version;
				const model = configNode.model;
				if (version === "CUSTOM") {
					hidePins();
					pinSelect.append($("<option></option>").val("CUSTOM").text("CUSTOM"));
					pinSelect.val("CUSTOM");
					return;
				}

				const pinsArray = pinsMapDigitalInputPins[version][model];
				if (pinsArray.length !== 0) {
					const actualValue = pinSelect.val() || digitalReadNode.pin;
					pinSelect.empty();
					pinsArray.forEach((pin) => {
						pinSelect.append($("<option></option>").val(pin).text(pin))
					});
					pinSelect.append($("<option></option>")
						.val("Message passed").text("Message passed"))
					// Replace if some pin was already set in the node
					if (pinsArray.includes(actualValue) || actualValue === "Message passed") {
						pinSelect.val(actualValue);
					}
					// Clean the error border if present
					if (pinSelect.hasClass("input-error")) {
						pinSelect.removeClass("input-error");
					}
					hideInputDiv.show();
				}
				else {
					hidePins();
				}
			});
		},
	});
</script>

<script type="text/x-red" data-template-name="rpiplc-digital-read">
	<div class="form-row">
		<label for="node-input-rpiplc"><i class="fa fa-cog"></i> PLC type</label>
		<input type="text" id="node-input-rpiplc" placeholder="PLC type">
	</div>
	<div class="form-row" id="hide-node-input-pin">
		<label for="node-input-pin"><i class="fa fa-circle-o"></i> Input</label>
		<select id="node-input-pin" placeholder="Select an input"></select>
	</div>
	<div class="form-row">
		<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
		<input type="text" id="node-input-name" placeholder="Name">
	</div>
</script>

<script type="text/x-red" data-help-name="rpiplc-digital-read">
  <p>
    <b>Digital Read</b>
  </p>
  <p>
    Returns the digital read of a pin as a payload. It also returns a <code>msg.rc</code> attribute to check if the digital read was successful.
  </p>
  <p>
    If the selected pin is <code>Message passed</code> or if the configuration node is custom, this node will read the <code>msg.pin</code> attribute to determine which pin to read from.
  </p>
  <p>
    See also the <a href="https://www.industrialshields.com/blog/raspberry-pi-for-industry-26/post/node-red-tutorial-how-to-read-digital-inputs-from-raspberry-plc-333">online documentation</a> for more information.
  </p>
</script>
